#include <iostream>
#include <thread>
#include <list>
using namespace std;


//// P6

class MessageList
{
private:
    list<int> msgRecvQueue;
public:
    // 收集命令
    void inMsgRecvQueue()
    {
        for(int i=0;i<100000;i++)
        {
            cout<<"inMsgRecvQueue()执行,插入一个元素 : command= "<<i<<endl;
            msgRecvQueue.push_back(i);
        }
    }

    void outMsgRecvQueue()
    {
        for(int i=0;i<100000;i++)
        {
            if(!msgRecvQueue.empty())
            {
                int command = msgRecvQueue.front(); //返回第一个元素，但不检查元素是否存在
                msgRecvQueue.pop_front();
                cout<<"outMsgRecvQueue()执行,command = "<<command<<endl;
            }
            else
            {
                cout<<"outMsgRecvQueue()执行,但目前消息队列为空格"<<endl;
            }
        }
        cout<<"outMsgRecvQueue()执行完成"<<endl;
    }
};

int main()
{
    /*一: 传递 临时对象 作为线程参数
        1.1 要避免的陷阱 

        总结
        1.如果传递 int 这种简单类型，建议都是值传递，不要有引用
        2.如果传递类对象，避免隐式类型转换。全部都爱创建线程这一行构建出。在函数参数用引用来接
    
    */
    int myval = 1;
    int & ref= myval;
    char mybuf[] = "this is a test";
    
     /*二 数据共享问题分析
     (2.1) 只读问题，是安全稳定的，不需要特别处理，直接读就可以了
     (2.2) 有读有写
            读时不能写
            写时不能读
    */

    /*三 数据共享问题代码分析
        网络游戏服务器 两个自己创建的线程 
            一个收集玩家命令 放入队列
            一个从队列取命令 解析执行
    */
    MessageList msgList;
    //第二个参数是引用，保证 线程里面使用的是用一个对象
    thread t1(&MessageList::inMsgRecvQueue,&msgList);
    thread t2(&MessageList::outMsgRecvQueue,&msgList);
    t1.join();
    t2.join();

}